/**
 * 实验设计router
 */

import path from "path";
import fs from "fs";
import express from "express";
import nodexlsx from "node-xlsx";
import archiver from "archiver";
// const nodexlsx = require("node-xlsx").default;
import { Schema } from "mongoose";
import {
  addData,
  findAll,
  deleteData,
  findById,
  findOneByIdsync,
  updateData,
  upDateDataByIdsync,
  findDesignerByUserId,
  findDesignerlist,
  deleteReactionDesignerData,
} from "../mdb/controlDB";
import {
  baseResp,
  badResp,
  designerModalname,
  designerSchematype,
  userModalname,
  reactDesignertype,
  reactDesignerModalname,
} from "../common";
import { hasLoginUser } from "../utils/webtoken";

import { userschema } from "./user";

import { createUID, formatCurrentDate } from "../utils";
import math, { FIXEDINDEX } from "../utils/math";

const router = express.Router();

const designerschema = new Schema(designerSchematype, {
  timestamps: true,
});

const reactDdesignerschema = new Schema(reactDesignertype);

interface ITDesingerUserInfo {
  account: string;
  id: string;
}

interface ITDesinger {
  _id?: string;

  // 工作台名称
  name: string;

  // 工作台id
  workbench: string;

  // 实验描述
  desc: string;

  // 实验步骤
  step: number;

  // 用户信息
  userInfo: ITDesingerUserInfo;

  // 创建时间
  createdAt: string;

  // 更新时间
  updatedAt: string;

  slotShelf?: string;

  reactorSlotShelf?: string;

  reagents?: string;

  reagentsort?: string;

  reactors?: any;

  temperature: number;

  reactionTime: number;

  expTable: string;
}

interface ITDesingerData {
  data: ITDesinger;
}

// 反应试剂来源接口
interface ITReactorFromItem {
  amount: number;
  bottleName: string;
  slotName: string;
  uid: string;
}

// 反应试剂接口
interface ITReactorReagentItem {
  // 试剂总数
  mmol: number | null;

  volume: number | null;

  weight: number | null;

  type: number | null;

  // 试剂id
  reagentid: string;

  // 试管名
  tubeName: string;

  // 来源
  from: ITReactorFromItem[];
}

type TCopyReagent = Pick<
  ITReactorReagentItem,
  "mmol" | "reagentid" | "volume" | "weight" | "type"
>;

interface ITReagentBottleReactor {
  amount: number;
  tubeName: string;
  uid: string;
}

interface ITReagentFill {
  mmol: number;
  weight: number;
  volume: number;
  type: number;
}

interface ITReagentBottleInfo extends ITReagentFill {
  amount: number;
  defaultAmount: ITReagentFill;
  reagentId: string;
  reactors: ITReagentBottleReactor[];
}

type PartialITReagentBottleInfo = Partial<ITReagentBottleInfo>;

interface ITReagentBottle {
  [bottleName: string]: PartialITReagentBottleInfo;
}

interface ITReagent {
  [slotName: string]: ITReagentBottle;
}

const formatSingleDesignerData = ({ data }: ITDesingerData) => {
  const {
    name,
    workbench,
    desc,
    userInfo,
    step,
    _id,
    createdAt,
    updatedAt,
    slotShelf,
    reactorSlotShelf,
    reagents,
    reactors,
    temperature,
    reactionTime,
    reagentsort,
    expTable,
  } = data;

  let tempSlotShelf = null;
  let tempReactorSlotShelf = null;
  let tempReagents = null;
  let tempReactors = null;
  let tempReagentsort = null;
  if (slotShelf) {
    try {
      tempSlotShelf = JSON.parse(slotShelf);
    } catch (e) {}
  }
  if (reactorSlotShelf) {
    try {
      tempReactorSlotShelf = JSON.parse(reactorSlotShelf);
    } catch (e) {}
  }
  if (reagents) {
    try {
      tempReagents = JSON.parse(reagents);
    } catch (e) {}
  }
  if (reactors) {
    try {
      tempReactors = JSON.parse(reactors);
    } catch (e) {}
  }

  if (reagentsort) {
    try {
      tempReagentsort = JSON.parse(reagentsort);
    } catch (e) {}
  }

  return {
    name,
    workbench,
    desc,
    userInfo,
    step,
    id: _id,
    slotShelf: tempSlotShelf,
    reactorSlotShelf: tempReactorSlotShelf,
    reactors: tempReactors,
    reagents: tempReagents,
    createdTime: new Date(createdAt).getTime(),
    updateTime: new Date(updatedAt).getTime(),
    temperature,
    reactionTime,
    expTable,
    reagentsort: tempReagentsort,
  };
};

const formatAllDesignerData = (data: ITDesinger) => {
  const {
    name,
    workbench,
    desc,
    userInfo,
    step,
    _id,
    createdAt,
    updatedAt,
    expTable,
  } = data;

  return {
    name,
    workbench,
    desc,
    userInfo,
    step,
    id: _id,
    createdTime: new Date(createdAt).getTime(),
    updateTime: new Date(updatedAt).getTime(),
    expTable,
  };
};

const formatResponseData = (data: ITDesinger) => {
  const {
    name,
    workbench,
    desc,
    userInfo,
    step,
    _id,
    createdAt,
    updatedAt,
    slotShelf,
    reactorSlotShelf,
    reagents,
    expTable,
  } = data;

  let tempSlotShelf = null;
  let tempReactorSlotShelf = null;
  // let tempReagents = null;
  if (slotShelf) {
    try {
      tempSlotShelf = JSON.parse(slotShelf);
    } catch (e) {}
  }
  if (reactorSlotShelf) {
    try {
      tempReactorSlotShelf = JSON.parse(reactorSlotShelf);
    } catch (e) {}
  }
  // if (reagents) {
  //   try {
  //     tempReagents = JSON.parse(reagents);
  //   } catch (e) {}
  // }

  return {
    name,
    workbench,
    desc,
    userInfo,
    step,
    id: _id,
    slotShelf: tempSlotShelf,
    reactorSlotShelf: tempReactorSlotShelf,
    reagents,
    createdTime: new Date(createdAt).getTime(),
    updateTime: new Date(updatedAt).getTime(),
    expTable,
  };
};

// 新增实验设计
router.post("/add", function (req, res) {
  const param = req.body;
  const { slotShelf, reactorSlotShelf } = param;
  param.step = 1;
  param.temperature = 25;
  param.reactionTime = 1;

  let tempParam = Object.assign({}, param);
  if (slotShelf) {
    tempParam = Object.assign({}, tempParam, {
      slotShelf: JSON.stringify(slotShelf),
    });
  }
  if (reactorSlotShelf) {
    tempParam = Object.assign({}, tempParam, {
      reactorSlotShelf: JSON.stringify(reactorSlotShelf),
    });
  }

  const addback = (data: any) => {
    if (data.success === false) {
      res.json(Object.assign({}, baseResp, data));
    } else {
      res.json(
        Object.assign({}, baseResp, {
          data: formatResponseData(data),
        })
      );
    }
  };

  addData({
    schematype: designerschema,
    callback: addback,
    modalname: designerModalname,
    param: tempParam,
  });
});

// 查询所有实验设计
router.get("/all", async function (req, res) {
  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };

  let userId = null;
  hasLoginUser.some((item) => {
    if (item.token === req.headers.token) {
      userId = item.id;
      return true;
    }
    return false;
  });
  if (userId) {
    const result: any = await findOneByIdsync({
      schematype: userschema,
      modalname: userModalname,
      param: { id: userId },
    });
    const { privilege } = result;
    // admin用户显示所有实验
    if (privilege === "admin") {
      const findBack = (data: any) => {
        let list: any[] = [];
        if (data && data.length) {
          data.forEach((element: any) => {
            list.push(formatAllDesignerData(element));
          });
        }
        res.json(Object.assign({}, baseResp, { data: list }));
      };
      findAll({
        schematype: designerschema,
        callback: findBack,
        modalname: designerModalname,
      });
    } else {
      // 非admin用户只显示该用户实验
      const result = await findDesignerByUserId({
        schematype: designerschema,
        modalname: designerModalname,
        param: { userId },
      });
      let list: any[] = [];
      if (result && result.length) {
        result.forEach((element: any) => {
          list.push(formatAllDesignerData(element));
        });
      }
      res.json(Object.assign({}, baseResp, { data: list }));
    }
  } else {
    badReq();
  }
});

// 删除实验设计
router.post("/del", async function (req, res) {
  const param = req.body;
  const delback = (data: any) => {
    // 还要删除实验设计对应的实验记录
    deleteReactionDesignerData({
      schematype: reactDdesignerschema,
      callback: () => {},
      modalname: reactDesignerModalname,
      param: param,
    });
    res.json(Object.assign({}, baseResp, data));
  };

  await deleteData({
    schematype: designerschema,
    callback: delback,
    modalname: designerModalname,
    param,
  });
});

// 根据id查询实验设计实验设计
router.post("/detail", (req, res) => {
  const param = req.body;
  if (!param.id) {
    res.json(Object.assign({}, badResp));
  } else {
    const findback = (data: any) => {
      if (data.success === false) {
        res.json(Object.assign({}, baseResp, data));
      } else {
        res.json(
          Object.assign({}, baseResp, {
            data: formatSingleDesignerData({
              data: data[0],
            }),
          })
        );
      }
    };

    // 根据id请求实验信息
    findById({
      schematype: designerschema,
      callback: findback,
      modalname: designerModalname,
      param,
    });
  }
});

// 更新实验设计
router.post("/update", (req, res) => {
  const param = req.body;
  const { slotShelf, reactorSlotShelf, reagents, reactors, reagentsort } =
    param;
  const editback = (data: any) => {
    res.json(Object.assign({}, baseResp));
  };

  let tempParam = Object.assign({}, param);
  if (slotShelf) {
    tempParam = Object.assign({}, tempParam, {
      slotShelf: JSON.stringify(slotShelf),
    });
  }
  if (reactorSlotShelf) {
    tempParam = Object.assign({}, tempParam, {
      reactorSlotShelf: JSON.stringify(reactorSlotShelf),
    });
  }
  if (reagents) {
    tempParam = Object.assign({}, tempParam, {
      reagents: JSON.stringify(reagents),
    });
  }
  if (reactors) {
    tempParam = Object.assign({}, tempParam, {
      reactors: JSON.stringify(reactors),
    });
  }
  if (reagentsort) {
    tempParam.reagentsort = JSON.stringify(reagentsort);
  }
  updateData({
    schematype: designerschema,
    callback: editback,
    modalname: designerModalname,
    param: tempParam,
  });
});

// 新增实验设计试剂
router.post("/addreagent", async (req, res) => {
  const { slotName, bottleName, designerId, data } = req.body;
  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };
  let result: any = null;
  try {
    // 先找出实验设计数据
    result = await findOneByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: { id: designerId },
    });
  } catch (e) {
    badReq();
  }

  if (result) {
    const { reagents = null, reagentsort = null } = result;
    try {
      let reagentsjson: ITReagent = JSON.parse(reagents);
      if (!reagentsjson) {
        reagentsjson = {};
      }
      if (!reagentsjson[slotName]) {
        reagentsjson[slotName] = {};
      }
      if (!reagentsjson[slotName][bottleName]) {
        reagentsjson[slotName][bottleName] = {};
      }
      reagentsjson[slotName][bottleName] = {
        ...data,
        defaultAmount: data,
      };
      let reagentSortSet = new Set();
      if (reagentsort) {
        const reagentsortJson = JSON.parse(reagentsort);
        reagentSortSet = new Set(reagentsortJson);
      }
      reagentSortSet.add(data.reagentId);

      const reagentString: string = JSON.stringify(reagentsjson);
      const addResult = await upDateDataByIdsync({
        schematype: designerschema,
        modalname: designerModalname,
        param: {
          id: designerId,
          reagents: reagentString,
          reagentsort: JSON.stringify(Array.from(reagentSortSet)),
        },
      });

      if (addResult) {
        res.json(Object.assign({}, baseResp));
      } else {
        badReq();
      }
    } catch (e) {
      badReq();
    }
  } else {
    badReq();
  }
});

router.post("/updatereagent", async (req, res) => {
  const { slotName, bottleName, designerId, data } = req.body;
  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };
  let result: any = null;
  try {
    // 先找出实验设计数据
    result = await findOneByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: { id: designerId },
    });
  } catch (e) {
    badReq();
  }

  if (result) {
    const { reagents } = result;

    try {
      const reagentsjson: ITReagent = JSON.parse(reagents);
      reagentsjson[slotName][bottleName] = {
        ...data,
        defaultAmount: data,
      };
      const reagentString = JSON.stringify(reagentsjson);
      const upResult = await upDateDataByIdsync({
        schematype: designerschema,
        modalname: designerModalname,
        param: {
          id: designerId,
          reagents: reagentString,
        },
      });

      if (upResult) {
        res.json(Object.assign({}, baseResp));
      } else {
        badReq();
      }
    } catch (e) {
      badReq();
    }
  } else {
    badReq();
  }
});

// 删除实验设计试剂
router.post("/deletereagent", async (req, res) => {
  const { slotName, bottleName, designerId } = req.body;
  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };
  let result: any = null;
  try {
    // 先找出实验设计数据
    result = await findOneByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: { id: designerId },
    });
  } catch (e) {
    badReq();
  }

  if (result) {
    const { reagents } = result;

    try {
      const reagentsjson: ITReagent = JSON.parse(reagents);
      delete reagentsjson[slotName][bottleName];
      const reagentString = JSON.stringify(reagentsjson);
      const deleteResult = await upDateDataByIdsync({
        schematype: designerschema,
        modalname: designerModalname,
        param: {
          id: designerId,
          reagents: reagentString,
        },
      });

      if (deleteResult) {
        res.json(Object.assign({}, baseResp));
      } else {
        badReq();
      }
    } catch (e) {
      badReq();
    }
  } else {
    badReq();
  }
});

// 新增实验设计反应试剂
// router.post("/addreactorreagent", async (req, res) => {
//   const { designerId, bottleName, data, step } = req.body;
//   const dataBak = { ...data, step };

//   const badReq = () => {
//     res.json(Object.assign({}, badResp));
//   };
//   let result: any = null;
//   try {
//     // 先找出实验设计数据
//     result = await findOneByIdsync({
//       schematype: designerschema,
//       modalname: designerModalname,
//       param: { id: designerId },
//     });
//   } catch (e) {
//     badReq();
//   }

//   if (result) {
//     const { reagents, reactors = null } = result;

//     let tempFrom: any = [];

//     // 扣除实验试剂
//     const reagentsJson = JSON.parse(reagents);
//     const slotNames = Object.keys(reagentsJson);
//     slotNames.forEach((slotName: string) => {
//       const reagetBottleObj = reagentsJson[slotName];
//       if (reagetBottleObj) {
//         const reagentBottles = Object.keys(reagetBottleObj);
//         reagentBottles.some((reagentBottleName: string) => {
//           const bottleReagentInfo = reagetBottleObj[reagentBottleName];
//           const reagentType = data.type;
//           if (bottleReagentInfo.reagentId === data.reagentid) {
//             const uid = createUID();

//             let isEnough = false;
//             // 液体采用volume === 1判断， 固体采用weight === 2判断
//             if (reagentType === 1) {
//               if (bottleReagentInfo.volume > 0 && bottleReagentInfo.volume >= data.volume) {
//                 isEnough = true;
//               }
//             } else if (reagentType === 2) {
//               if (bottleReagentInfo.weight > 0 && bottleReagentInfo.weight >= data.weight) {
//                 isEnough = true;
//               }
//             }

//             // 找到了试剂，判断份量是否足够
//             if (isEnough) {
//               // 分量足够，直接扣除
//               const reagentBottleInfo = reagentsJson[slotName][reagentBottleName];
//               let { reactors } = reagentBottleInfo;
//               if (!reactors) {
//                 reactors = [];
//               }

//               reactors.push({
//                 tubeName: bottleName,
//                 mmol: data.mmol,
//                 volume: data.volume,
//                 weight: data.weight,
//                 uid,
//               });
//               let tempMmol = null;
//               let tempWeight = null;
//               let tempVolume = null;
//               if (bottleReagentInfo.mmol > 0 && data.mmol > 0) {
//                 let tmp: any = math.format(math.evaluate(`${bottleReagentInfo.mmol} - ${data.mmol}`), FIXEDINDEX);
//                 // 剩余不能为负数
//                 tmp = tmp < 0 ? 0 : tmp;
//                 tempMmol = tmp - 0;
//               }
//               if (bottleReagentInfo.weight > 0 && data.weight > 0) {
//                 let tmp: any = math.format(math.evaluate(`${bottleReagentInfo.weight} - ${data.weight}`), FIXEDINDEX);
//                 tmp = tmp < 0 ? 0 : tmp;
//                 tempWeight = tmp - 0;
//               }
//               if (bottleReagentInfo.volume > 0 && data.volume > 0) {
//                 let tmp: any = math.format(math.evaluate(`${bottleReagentInfo.volume} - ${data.volume}`), FIXEDINDEX);
//                 tmp = tmp < 0 ? 0 : tmp;
//                 tempVolume = tmp - 0;
//               }
//               reagentsJson[slotName][reagentBottleName] = {
//                 ...reagentBottleInfo,
//                 mmol: tempMmol,
//                 weight: tempWeight,
//                 volume: tempVolume,
//                 reactors,
//               };

//               tempFrom.push({
//                 slotName,
//                 bottleName: reagentBottleName,
//                 mmol: data.mmol,
//                 volume: data.volume,
//                 weight: data.weight,
//                 uid,
//               });
//               return true;
//             } else {
//               // 分量不够，扣除可用分量，接下来找下一个然后扣除
//               const reagentBottleInfo =
//                 reagentsJson[slotName][reagentBottleName];
//               let { reactors } = reagentBottleInfo;
//               if (!reactors) {
//                 reactors = [];
//               }
//               if (bottleReagentInfo.mmol > 0 || bottleReagentInfo.weight > 0 || bottleReagentInfo.volume > 0) {
//                 reactors.push({
//                   tubeName: bottleName,
//                   mmol: bottleReagentInfo.mmol,
//                   weight: bottleReagentInfo.weight,
//                   volume: bottleReagentInfo.volume,
//                   uid,
//                 });
//               }

//               // 这里需要判断mmol 或 volume 或 weight 置0
//               let tempObj: any = {
//                 mmol: data.mmol !== null ? 0 : null,
//                 weight: data.weight !== null ? 0 : null,
//                 volume: data.volume !== null ? 0 : null
//               }

//               reagentsJson[slotName][reagentBottleName] = {
//                 ...reagentBottleInfo,
//                 ...tempObj,
//                 reactors,
//               };

//               if (bottleReagentInfo.mmol > 0 || bottleReagentInfo.weight > 0 || bottleReagentInfo.volume > 0) {
//                 tempFrom.push({
//                   slotName,
//                   bottleName: reagentBottleName,
//                   mmol: bottleReagentInfo.mmol,
//                   weight: bottleReagentInfo.weight,
//                   volume: bottleReagentInfo.volume,
//                   uid,
//                 });
//               }
//               if (data.mmol > 0 && bottleReagentInfo.mmol > 0) {
//                 let tmp: any = math.format(math.evaluate(`${data.mmol} - ${bottleReagentInfo.mmol}`), FIXEDINDEX);
//                 tmp = tmp < 0 ? 0 : tmp;
//                 data.mmol = tmp - 0;
//               }
//               if (data.weight > 0 && bottleReagentInfo.weight > 0) {
//                 let tmp: any = math.format(math.evaluate(`${data.weight} - ${bottleReagentInfo.weight}`), FIXEDINDEX);
//                 tmp = tmp < 0 ? 0 : tmp;
//                 data.weight = tmp - 0;
//               }
//               if (data.volume > 0 && bottleReagentInfo.volume > 0) {
//                 let tmp: any = math.format(math.evaluate(`${data.volume} - ${bottleReagentInfo.volume}`), FIXEDINDEX);
//                 tmp = tmp < 0 ? 0 : tmp;
//                 data.volume = tmp - 0;
//               }
//               return false;
//             }
//           }
//           return false;
//         });
//       }
//     });

//     // 新增反应试剂
//     let reactorsJson: ITReactorReagentItem[] | null = JSON.parse(reactors);
//     if (!reactorsJson) {
//       reactorsJson = [];
//     }
//     reactorsJson.push({
//       ...dataBak,
//       tubeName: bottleName,
//       from: tempFrom,
//     });

//     const reagentString = JSON.stringify(reagentsJson);
//     const reactorString = JSON.stringify(reactorsJson);

//     const upResult = await upDateDataByIdsync({
//       schematype: designerschema,
//       modalname: designerModalname,
//       param: {
//         id: designerId,
//         reagents: reagentString,
//         reactors: reactorString,
//       },
//     });

//     if (upResult) {
//       res.json(Object.assign({}, baseResp));
//     } else {
//       badReq();
//     }
//   } else {
//     badReq();
//   }
// });

// 删除实验设计反应试剂
router.post("/deletereactorreagent", async function (req, res) {
  const { designerId, from } = req.body;

  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };
  let result: any = null;
  try {
    // 先找出实验设计数据
    result = await findOneByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: { id: designerId },
    });
  } catch (e) {
    badReq();
  }

  if (result) {
    const { reagents, reactors = null } = result;

    // 还原实验试剂
    const reagentsJson = JSON.parse(reagents);
    const slotNames = Object.keys(reagentsJson);
    slotNames.forEach((slotName: string) => {
      const reagetBottleObj = reagentsJson[slotName];
      if (reagetBottleObj) {
        const reagentBottles = Object.keys(reagetBottleObj);
        reagentBottles.some((reagentBottleName: string) => {
          const bottleReagentInfo = reagetBottleObj[reagentBottleName];
          const { reactors } = bottleReagentInfo;

          // 根据uid判断是否删除
          let delIndex: number = -1;
          if (reactors && reactors.length) {
            reactors.some((ritem: any, tindex: number) => {
              from.some((fitem: any) => {
                if (ritem.uid === fitem.uid) {
                  delIndex = tindex;

                  if (
                    reagentsJson[slotName][reagentBottleName].mmol !== null &&
                    fitem.mmol !== null
                  ) {
                    let temp: any = math.format(
                      math.evaluate(
                        `${reagentsJson[slotName][reagentBottleName].mmol} + ${fitem.mmol}`
                      ),
                      FIXEDINDEX
                    );
                    reagentsJson[slotName][reagentBottleName].mmol = temp - 0;
                  }

                  if (
                    reagentsJson[slotName][reagentBottleName].weight !== null &&
                    fitem.weight !== null
                  ) {
                    let temp: any = math.format(
                      math.evaluate(
                        `${reagentsJson[slotName][reagentBottleName].weight} + ${fitem.weight}`
                      ),
                      FIXEDINDEX
                    );
                    reagentsJson[slotName][reagentBottleName].weight = temp - 0;
                  }

                  if (
                    reagentsJson[slotName][reagentBottleName].volume !== null &&
                    fitem.volume !== null
                  ) {
                    let temp: any = math.format(
                      math.evaluate(
                        `${reagentsJson[slotName][reagentBottleName].volume} + ${fitem.volume}`
                      ),
                      FIXEDINDEX
                    );
                    reagentsJson[slotName][reagentBottleName].volume = temp - 0;
                  }
                  return true;
                }
                return false;
              });
            });

            if (delIndex > -1) {
              reagentsJson[slotName][reagentBottleName].reactors.splice(
                delIndex,
                1
              );
            }
          }
        });
      }
    });

    // 删除反应试剂
    const reactorsJson: ITReactorReagentItem[] = JSON.parse(reactors);
    if (reactorsJson && reactorsJson.length) {
      let delIndex = -1;
      reactorsJson.some((item: any, index: number) => {
        if (item.from && item.from.length) {
          return item.from.some((ritem: any) => {
            return from.some((fitem: any) => {
              if (ritem.uid === fitem.uid) {
                delIndex = index;
                return true;
              }
              return false;
            });
          });
        }
        return false;
      });
      if (delIndex >= 0) {
        reactorsJson.splice(delIndex, 1);
      }
    }

    const reagentString = JSON.stringify(reagentsJson);
    const reactorString = JSON.stringify(reactorsJson);

    const upResult = await upDateDataByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: {
        id: designerId,
        reagents: reagentString,
        reactors: reactorString,
      },
    });

    if (upResult) {
      res.json(Object.assign({}, baseResp));
    } else {
      badReq();
    }
  } else {
    badReq();
  }
});

// 清除所有实验设计反应试剂
router.post("/clearreactorreagent", async function (req, res) {
  const { designerId, tubeName } = req.body;

  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };
  let result: any = null;
  try {
    // 先找出实验设计数据
    result = await findOneByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: { id: designerId },
    });
  } catch (e) {
    badReq();
  }

  if (result) {
    const { reagents, reactors = null } = result;

    // 删除反应试剂
    const reactorsJson: ITReactorReagentItem[] = JSON.parse(reactors);
    const tempReactorJson: any = [];
    const deleteFroms: any = [];
    if (reactorsJson && reactorsJson.length) {
      reactorsJson.forEach((item: any, index: number) => {
        if (item.tubeName === tubeName) {
          deleteFroms.push([...item.from]);
        } else {
          tempReactorJson.push(item);
        }
      });
    }

    // 还原实验试剂
    const reagentsJson = JSON.parse(reagents);
    if (deleteFroms.length) {
      const slotNames = Object.keys(reagentsJson);
      deleteFroms.forEach((from: any) => {
        slotNames.forEach((slotName: string) => {
          const reagetBottleObj = reagentsJson[slotName];
          if (reagetBottleObj) {
            const reagentBottles = Object.keys(reagetBottleObj);
            reagentBottles.some((reagentBottleName: string) => {
              const bottleReagentInfo = reagetBottleObj[reagentBottleName];
              const { reactors } = bottleReagentInfo;

              // 根据uid判断是否删除
              let delIndex: number = -1;
              if (reactors && reactors.length) {
                reactors.some((ritem: any, tindex: number) => {
                  from.some((fitem: any) => {
                    if (ritem.uid === fitem.uid) {
                      delIndex = tindex;

                      if (
                        reagentsJson[slotName][reagentBottleName].mmol !==
                          null &&
                        fitem.mmol !== null
                      ) {
                        let temp: any = math.format(
                          math.evaluate(
                            `${reagentsJson[slotName][reagentBottleName].mmol} + ${fitem.mmol}`
                          ),
                          FIXEDINDEX
                        );
                        reagentsJson[slotName][reagentBottleName].mmol =
                          temp - 0;
                      }

                      if (
                        reagentsJson[slotName][reagentBottleName].weight !==
                          null &&
                        fitem.weight !== null
                      ) {
                        let temp: any = math.format(
                          math.evaluate(
                            `${reagentsJson[slotName][reagentBottleName].weight} + ${fitem.weight}`
                          ),
                          FIXEDINDEX
                        );
                        reagentsJson[slotName][reagentBottleName].weight =
                          temp - 0;
                      }

                      if (
                        reagentsJson[slotName][reagentBottleName].volume !==
                          null &&
                        fitem.volume !== null
                      ) {
                        let temp: any = math.format(
                          math.evaluate(
                            `${reagentsJson[slotName][reagentBottleName].volume} + ${fitem.volume}`
                          ),
                          FIXEDINDEX
                        );
                        reagentsJson[slotName][reagentBottleName].volume =
                          temp - 0;
                      }

                      return true;
                    }
                    return false;
                  });
                });

                if (delIndex > -1) {
                  reagentsJson[slotName][reagentBottleName].reactors.splice(
                    delIndex,
                    1
                  );
                }
              }
            });
          }
        });
      });
    }

    const reagentString = JSON.stringify(reagentsJson);
    const reactorString = JSON.stringify(tempReactorJson);

    const upResult = await upDateDataByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: {
        id: designerId,
        reagents: reagentString,
        reactors: reactorString,
      },
    });

    if (upResult) {
      res.json(Object.assign({}, baseResp));
    } else {
      badReq();
    }
  } else {
    badReq();
  }
});

// 修改反应试剂
router.post("/updatereactorreagent", async function (req, res) {
  const { designerId, from, reagentid, data, tubeName } = req.body;
  const dataBak = { ...data };
  let bottleName = tubeName;

  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };
  let result: any = null;
  try {
    // 先找出实验设计数据
    result = await findOneByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: { id: designerId },
    });
  } catch (e) {
    badReq();
  }

  if (result) {
    const { reagents, reactors = null } = result;

    // 还原实验试剂
    const reagentsJson = JSON.parse(reagents);
    const slotNames = Object.keys(reagentsJson);
    slotNames.forEach((slotName: string) => {
      const reagetBottleObj = reagentsJson[slotName];
      if (reagetBottleObj) {
        const reagentBottles = Object.keys(reagetBottleObj);
        reagentBottles.some((reagentBottleName: string) => {
          const bottleReagentInfo = reagetBottleObj[reagentBottleName];
          const { reactors } = bottleReagentInfo;

          // 根据uid判断是否删除
          let delIndex: number = -1;
          if (reactors && reactors.length) {
            reactors.some((ritem: any, tindex: number) => {
              from.some((fitem: any) => {
                if (ritem.uid === fitem.uid) {
                  delIndex = tindex;

                  if (
                    reagentsJson[slotName][reagentBottleName].mmol !== null &&
                    fitem.mmol !== null
                  ) {
                    let temp: any = math.format(
                      math.evaluate(
                        `${reagentsJson[slotName][reagentBottleName].mmol} + ${fitem.mmol}`
                      ),
                      FIXEDINDEX
                    );
                    reagentsJson[slotName][reagentBottleName].mmol = temp - 0;
                  }

                  if (
                    reagentsJson[slotName][reagentBottleName].weight !== null &&
                    fitem.weight !== null
                  ) {
                    let temp: any = math.format(
                      math.evaluate(
                        `${reagentsJson[slotName][reagentBottleName].weight} + ${fitem.weight}`
                      ),
                      FIXEDINDEX
                    );
                    reagentsJson[slotName][reagentBottleName].weight = temp - 0;
                  }

                  if (
                    reagentsJson[slotName][reagentBottleName].volume !== null &&
                    fitem.volume !== null
                  ) {
                    let temp: any = math.format(
                      math.evaluate(
                        `${reagentsJson[slotName][reagentBottleName].volume} + ${fitem.volume}`
                      ),
                      FIXEDINDEX
                    );
                    reagentsJson[slotName][reagentBottleName].volume = temp - 0;
                  }

                  return true;
                }
                return false;
              });
            });

            if (delIndex > -1) {
              reagentsJson[slotName][reagentBottleName].reactors.splice(
                delIndex,
                1
              );
            }
          }
        });
      }
    });

    // 找出反应试剂所在的位置，然后直接替换反应试剂信息
    const reactorsJson: ITReactorReagentItem[] = JSON.parse(reactors);
    let delIndex = -1;
    if (reactorsJson && reactorsJson.length) {
      reactorsJson.some((item: any, index: number) => {
        if (item.from && item.from.length) {
          return item.from.some((ritem: any) => {
            return from.some((fitem: any) => {
              if (ritem.uid === fitem.uid) {
                delIndex = index;
                return true;
              }
              return false;
            });
          });
        }
        return false;
      });
    }

    // 扣除实验试剂
    let tempFrom: any = [];
    slotNames.forEach((slotName: string) => {
      const reagetBottleObj = reagentsJson[slotName];
      if (reagetBottleObj) {
        const reagentBottles = Object.keys(reagetBottleObj);
        reagentBottles.some((reagentBottleName: string) => {
          const bottleReagentInfo = reagetBottleObj[reagentBottleName];
          const reagentType = data.type;
          if (bottleReagentInfo.reagentId === data.reagentid) {
            const uid = createUID();

            let isEnough = false;
            if (reagentType === 1) {
              if (
                bottleReagentInfo.volume > 0 &&
                bottleReagentInfo.volume >= data.volume
              ) {
                isEnough = true;
              }
            } else if (reagentType === 2) {
              if (
                bottleReagentInfo.weight > 0 &&
                bottleReagentInfo.weight >= data.weight
              ) {
                isEnough = true;
              }
            }

            // 找到了试剂，判断份量是否足够
            if (isEnough) {
              // 分量足够，直接扣除
              const reagentBottleInfo =
                reagentsJson[slotName][reagentBottleName];
              let { reactors } = reagentBottleInfo;
              if (!reactors) {
                reactors = [];
              }

              reactors.push({
                tubeName: bottleName,
                mmol: data.mmol,
                volume: data.volume,
                weight: data.weight,
                uid,
              });

              let tempMmol = null;
              let tempWeight = null;
              let tempVolume = null;
              if (bottleReagentInfo.mmol > 0 && data.mmol > 0) {
                let tmp: any = math.format(
                  math.evaluate(`${bottleReagentInfo.mmol} - ${data.mmol}`),
                  FIXEDINDEX
                );
                // 剩余不能为负数
                tmp = tmp < 0 ? 0 : tmp;
                tempMmol = tmp - 0;
              }
              if (bottleReagentInfo.weight > 0 && data.weight > 0) {
                let tmp: any = math.format(
                  math.evaluate(`${bottleReagentInfo.weight} - ${data.weight}`),
                  FIXEDINDEX
                );
                tmp = tmp < 0 ? 0 : tmp;
                tempWeight = tmp - 0;
              }
              if (bottleReagentInfo.volume > 0 && data.volume > 0) {
                let tmp: any = math.format(
                  math.evaluate(`${bottleReagentInfo.volume} - ${data.volume}`),
                  FIXEDINDEX
                );
                tmp = tmp < 0 ? 0 : tmp;
                tempVolume = tmp - 0;
              }
              reagentsJson[slotName][reagentBottleName] = {
                ...reagentBottleInfo,
                mmol: tempMmol,
                weight: tempWeight,
                volume: tempVolume,
                reactors,
              };

              tempFrom.push({
                slotName,
                bottleName: reagentBottleName,
                mmol: data.mmol,
                volume: data.volume,
                weight: data.weight,
                uid,
              });
              return true;
            } else {
              // 分量不够，扣除可用分量，接下来找下一个然后扣除
              const reagentBottleInfo =
                reagentsJson[slotName][reagentBottleName];
              let { reactors } = reagentBottleInfo;
              if (!reactors) {
                reactors = [];
              }
              if (
                bottleReagentInfo.mmol > 0 ||
                bottleReagentInfo.weight > 0 ||
                bottleReagentInfo.volume > 0
              ) {
                reactors.push({
                  tubeName: bottleName,
                  mmol: bottleReagentInfo.mmol,
                  weight: bottleReagentInfo.weight,
                  volume: bottleReagentInfo.volume,
                  uid,
                });
              }

              // 这里需要判断mmol 或 volume 或 weight 置0
              let tempObj: any = {
                mmol: data.mmol !== null ? 0 : null,
                weight: data.weight !== null ? 0 : null,
                volume: data.volume !== null ? 0 : null,
              };

              reagentsJson[slotName][reagentBottleName] = {
                ...reagentBottleInfo,
                ...tempObj,
                reactors,
              };

              if (
                bottleReagentInfo.mmol > 0 ||
                bottleReagentInfo.weight > 0 ||
                bottleReagentInfo.volume > 0
              ) {
                tempFrom.push({
                  slotName,
                  bottleName: reagentBottleName,
                  mmol: bottleReagentInfo.mmol,
                  weight: bottleReagentInfo.weight,
                  volume: bottleReagentInfo.volume,
                  uid,
                });
              }
              if (data.mmol > 0 && bottleReagentInfo.mmol > 0) {
                let tmp: any = math.format(
                  math.evaluate(`${data.mmol} - ${bottleReagentInfo.mmol}`),
                  FIXEDINDEX
                );
                tmp = tmp < 0 ? 0 : tmp;
                data.mmol = tmp - 0;
              }
              if (data.weight > 0 && bottleReagentInfo.weight > 0) {
                let tmp: any = math.format(
                  math.evaluate(`${data.weight} - ${bottleReagentInfo.weight}`),
                  FIXEDINDEX
                );
                tmp = tmp < 0 ? 0 : tmp;
                data.weight = tmp - 0;
              }
              if (data.volume > 0 && bottleReagentInfo.volume > 0) {
                let tmp: any = math.format(
                  math.evaluate(`${data.volume} - ${bottleReagentInfo.volume}`),
                  FIXEDINDEX
                );
                tmp = tmp < 0 ? 0 : tmp;
                data.volume = tmp - 0;
              }
              return false;
            }
          }
          return false;
        });
      }
    });

    // 更新反应试剂
    if (delIndex >= 0) {
      reactorsJson[delIndex] = {
        ...dataBak,
        tubeName,
        from: tempFrom,
      };
    }

    const reagentString = JSON.stringify(reagentsJson);
    const reactorString = JSON.stringify(reactorsJson);

    const upResult = await upDateDataByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: {
        id: designerId,
        reagents: reagentString,
        reactors: reactorString,
      },
    });

    if (upResult) {
      res.json(Object.assign({}, baseResp));
    } else {
      badReq();
    }
  } else {
    badReq();
  }
});

// 复制反应试剂
router.post("/copyreactorreagent", async function (req, res) {
  let { designerId, tubes, tubeName, step, type } = req.body;

  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };
  let result: any = null;
  try {
    // 先找出实验设计数据
    result = await findOneByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: { id: designerId },
    });
  } catch (e) {
    badReq();
  }

  if (result) {
    const { reagents, reactors } = result;

    //找出需要复制的试剂
    const reactorsJson: ITReactorReagentItem[] = JSON.parse(reactors);
    let copyReagents: TCopyReagent[] = [];
    reactorsJson.forEach((item) => {
      const { mmol, volume, weight, type, reagentid } = item;
      if (item.tubeName === tubeName) {
        copyReagents.push({
          mmol,
          volume,
          weight,
          type,
          reagentid,
        });
      }
    });

    // 扣除实验试剂
    const reagentsJson = JSON.parse(reagents);
    const slotNames = Object.keys(reagentsJson);

    tubes.forEach((copyToTubeName: string) => {
      copyReagents.forEach((item) => {
        step++;
        const data: any = { ...item };
        const dataBak = { ...data, step };

        let tempFrom: any = [];
        slotNames.forEach((slotName: string) => {
          const reagetBottleObj = reagentsJson[slotName];
          if (reagetBottleObj) {
            const reagentBottles = Object.keys(reagetBottleObj);
            reagentBottles.some((reagentBottleName: string) => {
              const bottleReagentInfo = reagetBottleObj[reagentBottleName];
              const reagentType = type;
              if (bottleReagentInfo.reagentId === data.reagentid) {
                const uid = createUID();

                let isEnough = false;
                // 液体采用volume === 1判断， 固体采用weight === 2判断
                if (reagentType === 1) {
                  if (
                    bottleReagentInfo.volume > 0 &&
                    bottleReagentInfo.volume >= data.volume
                  ) {
                    isEnough = true;
                  }
                } else if (reagentType === 2) {
                  if (
                    bottleReagentInfo.weight > 0 &&
                    bottleReagentInfo.weight >= data.weight
                  ) {
                    isEnough = true;
                  }
                }

                // 找到了试剂，判断份量是否足够
                if (isEnough) {
                  // 分量足够，直接扣除
                  const reagentBottleInfo =
                    reagentsJson[slotName][reagentBottleName];
                  let { reactors } = reagentBottleInfo;
                  if (!reactors) {
                    reactors = [];
                  }

                  reactors.push({
                    tubeName: copyToTubeName,
                    mmol: data.mmol,
                    volume: data.volume,
                    weight: data.weight,
                    uid,
                  });
                  let tempMmol = null;
                  let tempWeight = null;
                  let tempVolume = null;
                  if (bottleReagentInfo.mmol > 0 && data.mmol > 0) {
                    let tmp: any = math.format(
                      math.evaluate(`${bottleReagentInfo.mmol} - ${data.mmol}`),
                      FIXEDINDEX
                    );
                    // 剩余不能为负数
                    tmp = tmp < 0 ? 0 : tmp;
                    tempMmol = tmp - 0;
                  }
                  if (bottleReagentInfo.weight > 0 && data.weight > 0) {
                    let tmp: any = math.format(
                      math.evaluate(
                        `${bottleReagentInfo.weight} - ${data.weight}`
                      ),
                      FIXEDINDEX
                    );
                    tmp = tmp < 0 ? 0 : tmp;
                    tempWeight = tmp - 0;
                  }
                  if (bottleReagentInfo.volume > 0 && data.volume > 0) {
                    let tmp: any = math.format(
                      math.evaluate(
                        `${bottleReagentInfo.volume} - ${data.volume}`
                      ),
                      FIXEDINDEX
                    );
                    tmp = tmp < 0 ? 0 : tmp;
                    tempVolume = tmp - 0;
                  }
                  reagentsJson[slotName][reagentBottleName] = {
                    ...reagentBottleInfo,
                    mmol: tempMmol,
                    weight: tempWeight,
                    volume: tempVolume,
                    reactors,
                  };

                  tempFrom.push({
                    slotName,
                    bottleName: reagentBottleName,
                    mmol: data.mmol,
                    volume: data.volume,
                    weight: data.weight,
                    uid,
                  });
                  return true;
                } else {
                  // 分量不够，扣除可用分量，接下来找下一个然后扣除
                  const reagentBottleInfo =
                    reagentsJson[slotName][reagentBottleName];
                  let { reactors } = reagentBottleInfo;
                  if (!reactors) {
                    reactors = [];
                  }
                  if (
                    bottleReagentInfo.mmol > 0 ||
                    bottleReagentInfo.weight > 0 ||
                    bottleReagentInfo.volume > 0
                  ) {
                    reactors.push({
                      tubeName: copyToTubeName,
                      mmol: bottleReagentInfo.mmol,
                      weight: bottleReagentInfo.weight,
                      volume: bottleReagentInfo.volume,
                      uid,
                    });
                  }

                  // 这里需要判断mmol 或 volume 或 weight 置0
                  let tempObj: any = {
                    mmol: data.mmol !== null ? 0 : null,
                    weight: data.weight !== null ? 0 : null,
                    volume: data.volume !== null ? 0 : null,
                  };

                  reagentsJson[slotName][reagentBottleName] = {
                    ...reagentBottleInfo,
                    ...tempObj,
                    reactors,
                  };

                  if (
                    bottleReagentInfo.mmol > 0 ||
                    bottleReagentInfo.weight > 0 ||
                    bottleReagentInfo.volume > 0
                  ) {
                    tempFrom.push({
                      slotName,
                      bottleName: reagentBottleName,
                      mmol: bottleReagentInfo.mmol,
                      weight: bottleReagentInfo.weight,
                      volume: bottleReagentInfo.volume,
                      uid,
                    });
                  }
                  if (data.mmol > 0 && bottleReagentInfo.mmol > 0) {
                    let tmp: any = math.format(
                      math.evaluate(`${data.mmol} - ${bottleReagentInfo.mmol}`),
                      FIXEDINDEX
                    );
                    tmp = tmp < 0 ? 0 : tmp;
                    data.mmol = tmp - 0;
                  }
                  if (data.weight > 0 && bottleReagentInfo.weight > 0) {
                    let tmp: any = math.format(
                      math.evaluate(
                        `${data.weight} - ${bottleReagentInfo.weight}`
                      ),
                      FIXEDINDEX
                    );
                    tmp = tmp < 0 ? 0 : tmp;
                    data.weight = tmp - 0;
                  }
                  if (data.volume > 0 && bottleReagentInfo.volume > 0) {
                    let tmp: any = math.format(
                      math.evaluate(
                        `${data.volume} - ${bottleReagentInfo.volume}`
                      ),
                      FIXEDINDEX
                    );
                    tmp = tmp < 0 ? 0 : tmp;
                    data.volume = tmp - 0;
                  }
                  return false;
                }
              }
              return false;
            });
          }
        });

        reactorsJson.push({
          ...dataBak,
          tubeName: copyToTubeName,
          from: tempFrom,
        });
      });
    });

    // 找出反应试剂所在的位置，然后直接替换反应试剂信息
    const reagentString = JSON.stringify(reagentsJson);
    const reactorString = JSON.stringify(reactorsJson);

    const upResult = await upDateDataByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: {
        id: designerId,
        reagents: reagentString,
        reactors: reactorString,
      },
    });

    if (upResult) {
      res.json(Object.assign({}, baseResp));
    } else {
      badReq();
    }
  } else {
    badReq();
  }
});

// 删除文件夹
const deleteFolder = (path: string, callback?: any) => {
  let files = [];
  if (fs.existsSync(path)) {
    files = fs.readdirSync(path);
    files.forEach((file) => {
      let curPath = path + "/" + file;
      if (fs.statSync(curPath).isDirectory()) {
        deleteFolder(curPath);
      } else {
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
    if (callback) {
      callback();
    }
  }
};

const createReagentExcelFile = ({
  designerReagentTitle,
  designerReagentList,
}: any) => {
  const data = [];
  if (
    designerReagentTitle &&
    designerReagentTitle.length &&
    designerReagentList &&
    designerReagentList.length
  ) {
    data.push(designerReagentTitle);
    designerReagentList.forEach((item: any) => {
      const ele = [];
      ele.push(item.name);
      ele.push(item.abbreviation);
      ele.push(item.cnname);
      ele.push(item.formula);
      ele.push(item.density);
      ele.push(item.percentage);
      ele.push(item.mw);
      ele.push(item.mp);
      ele.push(item.bp);
      ele.push(item.casno);
      ele.push(item.slotName);
      ele.push(item.bottleName);
      ele.push(item.type);
      ele.push(item.volatile);
      ele.push(item.viscose);
      ele.push(item.amount + " " + item.unit);
      ele.push(item.defaultAmount.mmol + " " + item.unitmmol);
      ele.push(item.defaultAmount.volume + " " + item.unitml);
      ele.push(item.defaultAmount.weight + " " + item.unitmg);
      ele.push(item.used + " " + item.unit);
      ele.push(item.usedMmol + " " + item.unitmmol);
      ele.push(item.usedVolume + " " + item.unitml);
      ele.push(item.usedWeight + " " + item.unitmg);
      ele.push(item.note);
      data.push(ele);
    });
  }

  const sheetOptions = {
    "!cols": [{ wch: 6 }, { wch: 7 }, { wch: 10 }, { wch: 20 }],
  };

  const buffer = nodexlsx.build([
    { name: "sheet1", data: data, options: sheetOptions },
  ]);
  return buffer;
};

const createReactExcelBuffer = ({ excelHeader, excelData }: any) => {
  let buffer = null;
  const xlsxData = [];
  xlsxData.push(excelHeader);
  if (excelData && excelData.length) {
    excelData.forEach((item: any) => {
      const ele: any = [];
      if (item && item.length) {
        item.forEach((value: any) => {
          ele.push(value);
        });
      }
      if (ele.length > 0) {
        xlsxData.push(ele);
      }
    });
  }
  if (xlsxData.length > 0) {
    const sheetOptions = {
      "!cols": [{ wch: 6 }, { wch: 7 }, { wch: 10 }, { wch: 20 }],
    };
    buffer = nodexlsx.build([
      { name: "sheet1", data: xlsxData, options: sheetOptions },
    ]);
  }
  return buffer;
};

// 导出实验设计
router.post("/exportdesigner", async function (req, res) {
  const { id, config, name, txt, excel, tuberackList } = req.body;
  let projectDir = path.join(__dirname, "../../project");
  if (process.env.NODE_ENV === "production") {
    // 给单机版使用
    projectDir = "C:/chemRoboxDesigner/html/project";
  }

  const folderName = `${projectDir}/${name}_${formatCurrentDate()}`;

  const writeFiles = (callback: any) => {
    fs.mkdir(folderName, async (err1) => {
      if (!err1) {
        const configFolerName = `${folderName}/config`;
        fs.mkdir(configFolerName, async (err2) => {
          if (!err2) {
            const configkeys = Object.keys(config);
            await configkeys.forEach(async (configName) => {
              await fs.writeFileSync(
                `${configFolerName}/${configName}.json`,
                JSON.stringify(config[configName])
              );
            });

            await tuberackList.forEach(async (item: any) => {
              const { name } = item;
              await fs.writeFileSync(
                `${configFolerName}/${name}.json`,
                JSON.stringify(item)
              );
            });

            let texts = "";
            txt.reactionMessage.forEach((txt: string) => {
              texts += txt + "\r\n";
            });
            await fs.writeFileSync(`${folderName}/reactionMessage.txt`, texts);

            const reagentLisbuffer = createReagentExcelFile(excel);
            await fs.writeFileSync(
              `${folderName}/reagentlist.xlsx`,
              reagentLisbuffer
            );

            callback();
          }
        });
      }
    });
  };

  const createZip = (callback: any) => {
    const fileName = `${name}_${formatCurrentDate()}.zip`;
    const output = fs.createWriteStream(`${projectDir}/${fileName}`);
    const archive = archiver("zip");
    archive.pipe(output);
    archive.directory(folderName, false);
    archive.finalize();
    if (callback) {
      callback(fileName);
    }
  };

  // 创建文件夹
  if (!fs.existsSync(folderName)) {
    writeFiles(() => {
      createZip((fileName: string) => {
        res.json(Object.assign({}, baseResp, { fileName }));
      });
    });
  } else {
    deleteFolder(folderName, () => {
      writeFiles(() => {
        createZip((fileName: string) => {
          res.json(Object.assign({}, baseResp, { fileName }));
        });
      });
    });
  }
});

router.post("/copydesigner", async (req, res) => {
  const { name, desc, designerId } = req.body;

  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };
  let result: any = null;
  try {
    // 先找出实验设计数据
    result = await findOneByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: { id: designerId },
    });
  } catch (e) {
    badReq();
  }

  const addback = (data: any) => {
    if (data.success === false) {
      res.json(Object.assign({}, baseResp, data));
    } else {
      res.json(Object.assign({}, baseResp));
    }
  };

  if (result) {
    let copyData: any = {
      name,
      desc,
      userInfo: result.userInfo,
      step: result.step,
      temperature: result.temperature,
      reactionTime: result.reactionTime,
      slotShelf: result.slotShelf,
      reactorSlotShelf: result.reactorSlotShelf,
      reactors: result.reactors,
      reagents: result.reagents,
      workbench: result.workbench,
    };
    addData({
      schematype: designerschema,
      callback: addback,
      modalname: designerModalname,
      param: copyData,
    });
  } else {
    badReq();
  }
});

// 修改反应步骤
router.post("/changestep", async function (req, res) {
  const { id, nextStep, step } = req.body;
  const badReq = () => {
    res.json(Object.assign({}, badResp));
  };
  let result: any = null;
  try {
    // 先找出实验设计数据
    result = await findOneByIdsync({
      schematype: designerschema,
      modalname: designerModalname,
      param: { id },
    });
  } catch (e) {
    badReq();
  }

  if (result) {
    const { reactors } = result;
    let reactorJson = null;
    try {
      reactorJson = JSON.parse(reactors);
    } catch (e) {}
    if (reactorJson) {
      let tempReactorArr: any = [];
      reactorJson.forEach((item: any) => {
        if (item.step === step) {
          item.step = nextStep;
        } else if (item.step === nextStep) {
          item.step = step;
        }
        tempReactorArr.push(item);
      });

      const tempReactorStr = JSON.stringify(tempReactorArr);
      const upResult = await upDateDataByIdsync({
        schematype: designerschema,
        modalname: designerModalname,
        param: {
          id,
          reactors: tempReactorStr,
        },
      });

      if (upResult) {
        res.json(Object.assign({}, baseResp));
      } else {
        badReq();
      }
    } else {
      badReq();
    }
  } else {
    badReq();
  }
});

router.post("/createreactexcel", async function (req, res) {
  const { id, name, excelHeader, excelData } = req.body;
  const buffer: any = createReactExcelBuffer({ excelHeader, excelData });
  let projectDir = path.join(__dirname, "../../project");
  if (process.env.NODE_ENV === "production") {
    // 给单机版使用
    projectDir = "C:/chemRoboxDesigner/html/project";
  }
  const fileName = `${name}_${formatCurrentDate()}.xlsx`;
  await fs.writeFileSync(`${projectDir}/${fileName}`, buffer);
  res.json(Object.assign({}, baseResp, { fileName }));
});

// 新增反应设计
router.post("/createreactdesigner", async function (req, res) {
  const param = req.body;

  const addback = (data: any) => {
    if (data.success === false) {
      res.json(Object.assign({}, baseResp, data));
    } else {
      res.json(
        Object.assign({}, baseResp, {
          data: formatResponseData(data),
        })
      );
    }
  };

  addData({
    schematype: reactDdesignerschema,
    callback: addback,
    modalname: reactDesignerModalname,
    param: param,
  });
  // res.json(Object.assign({}, baseResp, { fileName }));
});

router.post("/reactdesignerlist", async function (req, res) {
  const param = req.body;

  const findback = (data: any[]) => {
    res.json(Object.assign({}, baseResp, { data }));
  };

  findDesignerlist({
    schematype: reactDdesignerschema,
    callback: findback,
    modalname: reactDesignerModalname,
    param,
  });
});

router.post("/updatereactdesigner", async function (req, res) {
  const param = req.body;

  const editback = (data: any[]) => {
    res.json(Object.assign({}, baseResp, { data }));
  };

  updateData({
    schematype: reactDdesignerschema,
    callback: editback,
    modalname: reactDesignerModalname,
    param: param,
  });
});

router.post("/removereactdesigner", async function (req, res) {
  const param = req.body;

  const delback = (data: any) => {
    res.json(Object.assign({}, baseResp, data));
  };

  deleteData({
    schematype: reactDdesignerschema,
    callback: delback,
    modalname: reactDesignerModalname,
    param: param,
  });
});

router.post("/getreactdesigner", async function (req, res) {
  const param = req.body;

  const callback = (data: any) => {
    let temp = null;
    if (data.length) {
      temp = data[0];
    }
    res.json(Object.assign({}, baseResp, { data: temp }));
  };

  findById({
    schematype: reactDdesignerschema,
    callback: callback,
    modalname: reactDesignerModalname,
    param: param,
  });
});

export default router;
